1mod nexus;
20
21#[cfg(feature = "arc")]
22pub mod arc;
23
24#[cfg(feature = "extras")]
25pub mod extras;
26
27#[cfg(feature = "rtapi")]
28pub mod rtapi;
29
30use super::EventApi;
31use crate::{AddonApi, ffi::str_to_c, revertible::Revertible};
32use std::{
33 ffi::{c_char, c_void},
34 marker::PhantomData,
35 mem,
36};
37
38pub use self::nexus::*;
39
40#[derive(Debug, Clone, Copy)]
42pub struct Event<T> {
43 pub identifier: &'static str,
44 _phantom: PhantomData<T>,
45}
46
47impl<T> Event<T> {
48 #[inline]
53 pub const unsafe fn new(identifier: &'static str) -> Self {
54 Self {
55 identifier,
56 _phantom: PhantomData,
57 }
58 }
59
60 #[inline]
62 pub fn subscribe(
63 &self,
64 callback: RawEventConsume<T>,
65 ) -> Revertible<impl Fn() + Send + Sync + Clone + 'static> {
66 unsafe { event_subscribe_typed(self.identifier, callback) }
67 }
68
69 #[inline]
71 pub fn unsubscribe(&self, callback: RawEventConsume<T>) {
72 let callback =
73 unsafe { mem::transmute::<RawEventConsume<T>, RawEventConsumeUnknown>(callback) };
74 event_unsubscribe(self.identifier, callback)
75 }
76
77 #[inline]
79 pub fn raise(&self, event_data: &T) {
80 unsafe { event_raise(self.identifier, event_data) }
81 }
82}
83
84pub type RawEventConsume<T> = extern "C-unwind" fn(event_args: *const T);
85
86pub type RawEventConsumeUnknown = RawEventConsume<c_void>;
87
88pub type RawEventRaise =
89 unsafe extern "C-unwind" fn(identifier: *const c_char, event_data: *const c_void);
90
91pub type RawEventRaiseNotification = unsafe extern "C-unwind" fn(identifier: *const c_char);
92
93pub type RawEventRaiseTargeted = unsafe extern "C-unwind" fn(
94 signature: i32,
95 identifier: *const c_char,
96 event_data: *const c_void,
97);
98
99pub type RawEventRaiseNotificationTargeted =
100 unsafe extern "C-unwind" fn(signature: i32, identifier: *const c_char);
101
102pub type RawEventSubscribe = unsafe extern "C-unwind" fn(
103 identifier: *const c_char,
104 consume_callback: RawEventConsumeUnknown,
105);
106
107pub fn event_subscribe_unknown(
111 identifier: impl AsRef<str>,
112 callback: RawEventConsumeUnknown,
113) -> Revertible<impl Fn() + Send + Sync + Clone + 'static> {
114 let identifier = str_to_c(identifier).expect("failed to convert event identifier");
115 let EventApi {
116 subscribe,
117 unsubscribe,
118 ..
119 } = AddonApi::get().event;
120 unsafe { subscribe(identifier.as_ptr(), callback) };
121 let revert = move || unsafe { unsubscribe(identifier.as_ptr(), callback) };
122 revert.into()
123}
124
125pub unsafe fn event_subscribe_typed<T>(
132 identifier: impl AsRef<str>,
133 callback: RawEventConsume<T>,
134) -> Revertible<impl Fn() + Send + Sync + Clone + 'static> {
135 let callback =
136 unsafe { mem::transmute::<RawEventConsume<T>, RawEventConsumeUnknown>(callback) };
137 event_subscribe_unknown(identifier, callback)
138}
139
140pub fn event_unsubscribe(identifier: impl AsRef<str>, callback: RawEventConsumeUnknown) {
142 let identifier = str_to_c(identifier).expect("failed to convert event identifier");
143 let EventApi { unsubscribe, .. } = AddonApi::get().event;
144 unsafe { unsubscribe(identifier.as_ptr(), callback) }
145}
146
147#[macro_export]
188macro_rules! event_consume {
189 ( < $ty:ty > $callback:expr $(,)? ) => {{
190 const __CALLBACK: fn(::std::option::Option<&$ty>) = ($callback);
191
192 extern "C-unwind" fn __event_callback_wrapper(data: *const $ty) {
193 let _ = unsafe { ::std::mem::transmute::<*const $ty, *const ::std::ffi::c_void>(data) }; __CALLBACK(unsafe { data.as_ref() })
195 }
196
197 __event_callback_wrapper
198 }};
199 ( $ty:ty , $callback:expr $(,)? ) => {
200 $crate::event::event_consume!(<$ty> $callback)
201 };
202 ( | $arg:ident : Option<& $ty:ty > | $body:expr $(,)? ) => {
203 $crate::event::event_consume!(<$ty> |$arg: Option<& $ty >| $body)
204 };
205 ( $callback:expr $(,)? ) => {{
206 $crate::event::event_consume!(<()> $callback)
207 }};
208}
209
210pub use event_consume;
211
212#[macro_export]
265macro_rules! event_subscribe {
266 ( unsafe $event:expr , $ty:ty , $callback:expr $(,)? ) => {
267 unsafe { $crate::event::event_subscribe!($event => $ty, $callback) }
268 };
269 ( unsafe $event:expr => $ty:ty , $callback:expr $(,)? ) => {
270 unsafe { $crate::event::event_subscribe!($event => $ty, $callback) }
271 };
272 ( $event:expr , $ty:ty , $callback:expr $(,)? ) => {
273 $crate::event::event_subscribe!($event => $ty, $callback)
274 };
275 ( $event:expr => $ty:ty , $callback:expr $(,)? ) => {
276 $crate::event::event_subscribe_typed($event, $crate::event::event_consume!(<$ty> $callback))
277 };
278}
279
280pub use event_subscribe;
281
282pub unsafe fn event_raise<T>(identifier: impl AsRef<str>, event_data: &T) {
287 let identifier = str_to_c(identifier).expect("failed to convert event identifier");
288 let data: *const _ = event_data;
289 let EventApi { raise, .. } = AddonApi::get().event;
290 unsafe { raise(identifier.as_ptr(), data.cast()) }
291}
292
293pub fn event_raise_notification(identifier: impl AsRef<str>) {
295 let identifier = str_to_c(identifier).expect("failed to convert event identifier");
296 let EventApi {
297 raise_notification, ..
298 } = AddonApi::get().event;
299 unsafe { raise_notification(identifier.as_ptr()) }
300}
301
302pub unsafe fn event_raise_targeted<T>(signature: i32, identifier: impl AsRef<str>, event_data: &T) {
307 let identifier = str_to_c(identifier).expect("failed to convert event identifier");
308 let data: *const _ = event_data;
309 let EventApi { raise_targeted, .. } = AddonApi::get().event;
310 unsafe { raise_targeted(signature, identifier.as_ptr(), data.cast()) }
311}
312
313pub fn event_raise_notification_targeted(signature: i32, identifier: impl AsRef<str>) {
315 let identifier = str_to_c(identifier).expect("failed to convert event identifier");
316 let EventApi {
317 raise_notification_targeted,
318 ..
319 } = AddonApi::get().event;
320 unsafe { raise_notification_targeted(signature, identifier.as_ptr()) }
321}